package com.basic.library.httpmanager;


import android.content.Context;

import com.basic.library.R;

import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;


public class SslContextFactory {
    private static final String CLIENT_AGREEMENT = "TLS";//使用协议
    private static final String CLIENT_TRUST_MANAGER = "X509";
    private static final String CLIENT_TRUST_KEYSTORE = "BKS";
    private static final String CLIENT_TRUST_KEY = "PKCS12";
    private static final String CLIENT_TRUST_PROVIDER = "BC";
    public static String TRUST_CA_PWD = "1537685015591";
    public static String SELF_CERT_PWD = "123456";

    /**
     * 单项认证
     */
    public static SSLSocketFactory getSSLSocketFactoryForOneWay(InputStream... certificates) {
        try {
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null);
//            keyStore.load(certificates[0], TRUST_CA_PWD.toCharArray());
            int index = 0;
            for (InputStream certificate : certificates) {
                String certificateAlias = Integer.toString(index++);
                keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));
                try {
                    if (certificate != null)
                        certificate.close();
                } catch (IOException e) {
                    System.out.println(e.getMessage());
                    e.printStackTrace();
                }
            }

            SSLContext sslContext = SSLContext.getInstance(CLIENT_AGREEMENT);

            TrustManagerFactory trustManagerFactory =
                    TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(keyStore);

            sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
            return sslContext.getSocketFactory();
        } catch (Exception e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 双向认证
     *
     * @return SSLSocketFactory
     */
    public static SSLSocketFactory getSSLSocketFactoryForTwoWay(Context context) {
        SSLSocketFactory sslSocketFactory = null;
        try {
            // 服务器端需要验证的客户端证书，其实就是客户端的keystore
            KeyStore keyStore = KeyStore.getInstance(CLIENT_TRUST_KEY);// 客户端信任的服务器端证书
            KeyStore trustStore = KeyStore.getInstance(CLIENT_TRUST_KEYSTORE);//读取证书
            InputStream ksIn = context.getResources().openRawResource(R.raw.client);
            InputStream tsIn = context.getResources().openRawResource(R.raw.server);//加载证书
            keyStore.load(ksIn, SELF_CERT_PWD.toCharArray());
            trustStore.load(tsIn, TRUST_CA_PWD.toCharArray());
            ksIn.close();
            tsIn.close();
            //初始化SSLContext
            SSLContext sslContext = SSLContext.getInstance(CLIENT_AGREEMENT);
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(CLIENT_TRUST_MANAGER);
            trustManagerFactory.init(trustStore);
            keyManagerFactory.init(keyStore, SELF_CERT_PWD.toCharArray());
            sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
            sslSocketFactory = sslContext.getSocketFactory();
        } catch (Exception e) {

        }//省略各种异常处理，请自行添加
        return sslSocketFactory;
    }

////////////////    双向ssl证书

    private final static String SERVER_PFX_PASSWORD = "1537685015591";
    private final static String CLIENT_P12_PASSWORD = "123456";

    /**
     * 双向ssl证书
     *
     * @param context
     * @return
     */
    public static SSLSocketFactory getSSLSocketFactoryBilateral(Context context) {
        SSLContext sslContext = null;
        try {
            sslContext = SSLContext.getInstance("TLS");
            sslContext.init(getKeyManagerFactory(context).getKeyManagers(), getTrustManagerFactory(context).getTrustManagers(), null);
        } catch (NoSuchAlgorithmException | KeyManagementException e) {
            e.printStackTrace();
        }
        return sslContext != null ? sslContext.getSocketFactory() : null;
    }


    /**
     * client端     * @param context     * @return
     */
    public static KeyManagerFactory getKeyManagerFactory(Context context) {
        KeyStore keyStore = null;
        KeyManagerFactory keyManagerFactory = null;
        try {
            keyStore = KeyStore.getInstance("PKCS12");
            InputStream ksIn = context.getResources().openRawResource(R.raw.client);
            keyStore.load(ksIn, CLIENT_P12_PASSWORD.toCharArray());
            ksIn.close();
            keyManagerFactory = KeyManagerFactory.getInstance("X509");
            keyManagerFactory.init(keyStore, CLIENT_P12_PASSWORD.toCharArray());
        } catch (KeyStoreException | CertificateException | UnrecoverableKeyException | NoSuchAlgorithmException | IOException e) {
            e.printStackTrace();
        }
        return keyManagerFactory;
    }

    /**
     * server端     * @param context     * @return
     */
    public static TrustManagerFactory getTrustManagerFactory(Context context) {
        KeyStore trustStore = null;
        TrustManagerFactory trustManagerFactory = null;
        try {
            trustStore = KeyStore.getInstance("bks");
            InputStream tsIn = context.getResources().openRawResource(R.raw.server);
            trustStore.load(tsIn, SERVER_PFX_PASSWORD.toCharArray());
            trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(trustStore);
        } catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException e) {
            e.printStackTrace();
        }
        return trustManagerFactory;
    }
}

